<template>
  <view class="tui-charts__bar-wrap" :style="{ width: width + 'rpx' }">
    <view class="tui-bar__legend" v-if="legend.show">
      <view class="tui-bar__legend-item" v-for="(item, index) in dataset" :key="index">
        <view class="tui-legend__circle" :style="{ backgroundColor: item.color }"></view>
        <text
          :style="{
            fontSize: (legend.size || 24) + 'rpx',
            lineHeight: (legend.size || 24) + 'rpx',
            color: legend.color || '#333',
          }"
        >
          {{ item.name }}
        </text>
      </view>
    </view>
    <view
      class="tui-charts__bar-box"
      :style="{ borderLeftColor: yAxisLine.color, borderBottomColor: xAxisLineColor }"
      v-if="yAxis.length > 0 && dataset.length > 0"
    >
      <view
        class="tui-charts__bar-item"
        :class="{
          'tui-bar__item-stack': isStack,
          'tui-column__item-active': activeIndex === index && clickEffect == 1,
          'tui-column__bar-opacity': clickEffect == 2,
          'tui-column__bar-active': clickEffect == 2 && activeIndex == index,
        }"
        v-for="(item, index) in yAxis"
        :key="index"
        :style="{ padding: yAxisLine.itemPadding || '30rpx 0' }"
      >
        <view
          class="tui-charts__bar"
          :class="{ 'tui-charts__bar-round': columnCap === 'round' }"
          v-for="(bar, idx) in dataset"
          :key="idx"
          :style="{
            height: columnBarHeight + 'rpx',
            borderRightColor: getBarColor(bar.source[index], bar.color, bar.colorFormatter),
            background: getBarColor(bar.source[index], bar.color, bar.colorFormatter),
            width:
              ((bar.source[index] - (isStack ? min / dataset.length : min)) / (maxValue - min)) *
                width +
              'rpx',
          }"
          @tap.stop="onBarTap(index, idx)"
        ></view>
        <view
          class="tui-bar__val"
          v-if="
            (yAxisVal.show && clickEffect != 2) ||
            (yAxisVal.show && clickEffect == 2 && activeIndex === index)
          "
          :style="{
            color: yAxisVal.color,
            fontSize: (yAxisVal.size || 24) + 'rpx',
            whiteSpace: yAxisVal.nowrap ? 'nowrap' : 'normal',
            left: getLeft(index),
          }"
        >
          {{ getXAxisVal(index) }}
        </view>
        <view
          class="tui-bar__yAxis-text"
          :style="{ color: yAxisLabel.color || '#333', fontSize: (yAxisLabel.size || 24) + 'rpx' }"
        >
          {{ item }}
        </view>
        <view
          class="tui-yAxis__tickmarks"
          :style="{
            width: yAxisTick.width || '12rpx',
            backgroundColor: yAxisTick.color || '#e3e3e3',
          }"
        ></view>
      </view>
      <view class="tui-bar__yAxis-linebox">
        <view
          class="tui-bar__yAxis-line"
          :class="{ 'tui-yAxis__line-first': idx === 0 }"
          v-for="(item, idx) in xAxisData"
          :key="idx"
          :style="{ borderLeftStyle: splitLine.type, borderLeftColor: splitLine.color }"
        >
          <text
            class="tui-xAxis__val"
            :style="{
              color: item.color || xAxisLabel.color,
              fontSize: (xAxisLabel.size || 24) + 'rpx',
            }"
            v-if="xAxisLabel.show"
          >
            {{ item.value }}
          </text>
        </view>
      </view>
    </view>
    <view
      class="tui-column__tooltip"
      v-if="tooltip"
      :class="{ 'tui-column__tooltip-show': tooltipShow }"
    >
      <view class="tui-tooltip__title">{{ yAxis[activeIndex] || '' }}</view>
      <view class="tui-column__tooltip-item" v-for="(item, index) in tooltips" :key="index">
        <view class="tui-legend__circle" :style="{ backgroundColor: item.color }"></view>
        <text class="tui-tooltip__val">{{ item.name }}</text>
        <text class="tui-tooltip__val tui-tooltip__val-ml">{{ item.val }}</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'tui-charts-bar',
  emits: ['click'],
  props: {
    //图表宽度 rpx
    width: {
      type: [Number, String],
      default: 600,
    },
    //图例，说明
    legend: {
      type: Object,
      default() {
        return {
          show: false,
          size: 24,
          color: '#333',
        };
      },
    },
    tooltip: {
      type: Boolean,
      default: false,
    },
    //x轴数据，如果不传则默认使用min,max值计算
    // {
    // 	value: 0,
    // 	color: "#a0a0a0"
    // }
    xAxis: {
      type: Array,
      default() {
        return [];
      },
    },
    //x轴最小值
    min: {
      type: Number,
      default: 0,
    },
    //x轴最大值
    max: {
      type: Number,
      default: 100,
    },
    //x轴分段递增数值
    splitNumber: {
      type: Number,
      default: 20,
    },
    //分割线
    splitLine: {
      type: Object,
      default() {
        return {
          //分割线颜色,不显示则将颜色设置为transparent
          color: '#e3e3e3',
          type: 'dashed',
        };
      },
    },
    xAxisLineColor: {
      type: String,
      //不显示则将颜色设置为transparent
      default: '#e3e3e3',
    },
    xAxisLabel: {
      type: Object,
      default() {
        return {
          show: true,
          color: '#333',
          size: 24,
        };
      },
    },
    yAxis: {
      type: Array,
      default() {
        return [];
      },
    },
    //柱状条高度
    columnBarHeight: {
      type: [Number, String],
      default: 32,
    },
    //y轴刻度线
    yAxisTick: {
      type: Object,
      default() {
        return {
          width: '12rpx',
          //不显示则将颜色设置为transparent
          color: '#e3e3e3',
        };
      },
    },
    //y轴线条
    yAxisLine: {
      type: Object,
      default() {
        return {
          color: '#e3e3e3',
          //y轴item的padding值
          itemPadding: '30rpx 0',
        };
      },
    },
    yAxisLabel: {
      type: Object,
      default() {
        return {
          show: true,
          color: '#333',
          size: 24,
        };
      },
    },
    yAxisVal: {
      type: Object,
      default() {
        return {
          show: true,
          color: '#333',
          size: 24,
        };
      },
    },
    //默认选中y轴索引
    currentIndex: {
      type: Number,
      default: -1,
    },
    //是否堆叠展示
    isStack: {
      type: Boolean,
      default: false,
    },
    //柱状条点击效果：1-出现背景，2-高亮显示，其他变暗 3-无效果
    clickEffect: {
      type: Number,
      default: 1,
    },
    /*
				 柱状条的端点样式
				 round	向线条的每个末端添加圆形线帽
				 square	向线条的每个末端添加正方形线帽
				*/
    columnCap: {
      type: String,
      default: 'square',
    },
  },
  data() {
    return {
      sections: 0,
      xAxisData: [],
      activeIndex: -1,
      activeIdx: -1,
      tooltips: [],
      tooltipShow: false,
      timer: null,
      /*========options============*/
      /*
					name: '',
					color: '',
					source: []
					colorFormatter:Function
				*/
      dataset: [],
      yAxisValFormatter: null,
      maxValue: 1,
    };
  },
  watch: {
    xAxis(newVal) {
      this.init();
    },
    currentIndex(newVal) {
      if (newVal != this.activeIndex) {
        this.activeIndex = newVal;
      }
    },
  },
  // #ifndef VUE3
  beforeDestroy() {
    this.clearTimer();
  },
  // #endif
  // #ifdef VUE3
  beforeUnmount() {
    this.clearTimer();
  },
  // #endif
  created() {
    // this.maxValue = this.max;
    this.init();
    this.activeIndex = this.currentIndex;
  },
  methods: {
    generateArray(start, end) {
      return Array.from(new Array(end + 1).keys()).slice(start);
    },
    getXAxisVal(index) {
      let showVal = '';
      let val = 0;
      if (this.dataset.length === 1) {
        val = this.dataset[0].source[index];
        showVal = val;
      } else if (this.dataset.length > 1) {
        let arr = [];
        this.dataset.forEach((item) => {
          arr.push(item.source[index]);
        });
        val = arr;
      }
      if (this.yAxisVal.formatter && typeof this.yAxisVal.formatter === 'function') {
        showVal = this.yAxisVal.formatter(val);
      } else if (this.yAxisValFormatter && typeof this.yAxisValFormatter === 'function') {
        showVal = this.yAxisValFormatter(val);
      }
      return showVal;
    },
    getBarColor(val, color, colorFormatter) {
      let bgColor = color;
      if (colorFormatter && typeof colorFormatter === 'function') {
        let formatColor = colorFormatter(val);
        if (formatColor) {
          bgColor = formatColor;
        }
      }
      return bgColor;
    },
    getLeft(index) {
      let arr = [0];
      let total = 0;
      this.dataset.forEach((item) => {
        arr.push(item.source[index]);
        total += item.source[index];
      });
      return (
        (((this.isStack ? total : Math.max(...arr)) - this.min) / (this.maxValue - this.min)) *
          this.width +
        'rpx'
      );
    },
    init() {
      let sections = this.xAxis.length - 1;
      let xAxis = this.xAxis;
      this.maxValue = this.max;
      if (sections <= 0) {
        sections = Math.ceil((this.max - this.min) / this.splitNumber);
        let sectionsArr = this.generateArray(0, sections);

        xAxis = sectionsArr.map((item) => {
          return {
            value: item * this.splitNumber + this.min,
          };
        });
        this.maxValue = xAxis[xAxis.length - 1].value;
      }
      this.xAxisData = xAxis;
      this.sections = sections + 1;
    },
    clearTimer() {
      clearTimeout(this.timer);
      this.timer = null;
    },
    tooltipHandle(index) {
      let data = [...this.dataset];
      let tooltips = [];
      data.forEach((item) => {
        let color = item.color;
        if (item.colorFormatter && typeof item.colorFormatter === 'function') {
          color = item.colorFormatter(item.source[index]);
        }
        tooltips.push({
          color: color,
          name: item.name,
          val: item.source[index],
        });
      });
      this.tooltips = tooltips;
      this.clearTimer();
      this.tooltipShow = true;
      this.timer = setTimeout(() => {
        this.tooltipShow = false;
      }, 5000);
    },
    onBarTap(index, idx) {
      this.activeIndex = index;
      this.activeIdx = idx;
      this.tooltipHandle(index);
      this.$emit('click', {
        datasetIndex: idx,
        sourceIndex: index,
        ...this.dataset[idx],
      });
    },
    /*
			dataset：柱状图表数据
			yAxisValFormatter :格式化柱状条顶部value值（此处传值是为了做兼容处理）
			*/
    draw(dataset, yAxisValFormatter) {
      this.yAxisValFormatter = yAxisValFormatter || null;
      this.dataset = dataset || [];
      this.init();
    },
  },
};
</script>

<style scoped>
.tui-charts__bar-wrap {
  position: relative;
  margin: 0 auto;
}

.tui-bar__legend {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.tui-bar__legend-item {
  display: flex;
  align-items: center;
  margin-left: 24rpx;
  margin-bottom: 30rpx;
}

.tui-legend__circle {
  height: 20rpx;
  width: 20rpx;
  border-radius: 50%;
  margin-right: 8rpx;
  flex-shrink: 0;
}

.tui-charts__bar-box {
  position: relative;
  width: 100%;
  border-left: 1px solid;
  border-bottom: 1px solid;
  display: inline-flex;
  justify-content: space-between;
  flex-direction: column;
  z-index: 8;
}

.tui-charts__bar-item {
  position: relative;
  flex: 1;
  flex-shrink: 0;
  padding: 30rpx 0;
  display: inline-flex;
  flex-direction: column;
  z-index: 10;
  transition: all 0.3s;
}

.tui-bar__item-stack {
  flex-direction: row !important;
}

.tui-yAxis__tickmarks {
  position: absolute;
  width: 16rpx;
  height: 1px;
  background-color: #e3e3e3;
  left: 0;
  top: 0;
  transform: translateX(-100%);
  z-index: 10;
}

.tui-charts__bar {
  position: relative;
  transition: all 0.3s;
  text-align: center;
  /* #ifdef H5 */
  cursor: pointer;
  /* #endif */
  /* border-right: 1px solid; */
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  -webkit-font-smoothing: antialiased;
  /* position: relative; */
  flex-shrink: 0;
}

.tui-column__bar-opacity {
  opacity: 0.6;
}

.tui-column__bar-active {
  opacity: 0.9999;
}

.tui-column__item-active {
  background-color: rgba(0, 0, 0, 0.1);
}

.tui-charts__bar-round {
  border-top-right-radius: 100px;
  border-bottom-right-radius: 100px;
}

.tui-bar__val {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  padding-left: 12rpx;
  word-break: break-all;
  flex-shrink: 0;
  transition: left 0.3s;
}

.tui-bar__yAxis-text {
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 0;
  flex: 1;
  transform: translate(-100%, -50%);
  padding-right: 20rpx;
  word-break: break-all;
}

.tui-bar__yAxis-linebox {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  z-index: 6;
}

.tui-bar__yAxis-line {
  height: 100%;
  width: 0;
  border-left: 1px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  overflow: visible;
}

.tui-yAxis__line-first {
  border-left: 0 !important;
}

.tui-xAxis__val {
  transform: translateY(100%);
  padding-top: 12rpx;
}

.tui-column__tooltip {
  padding: 30rpx;
  border-radius: 12rpx;
  background-color: rgba(0, 0, 0, 0.6);
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 20;
  visibility: hidden;
  opacity: 0;
  transition: all 0.3s;
}

.tui-column__tooltip-show {
  visibility: visible;
  opacity: 1;
}

.tui-tooltip__title {
  font-size: 30rpx;
  color: #fff;
  line-height: 30rpx;
}

.tui-column__tooltip-item {
  display: flex;
  align-items: center;
  padding-top: 24rpx;
  white-space: nowrap;
}

.tui-tooltip__val {
  font-size: 24rpx;
  line-height: 24rpx;
  color: #fff;
  margin-left: 6rpx;
}

.tui-tooltip__val-ml {
  margin-left: 20rpx;
}
</style>
